import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"
import qs from "qs";

// 拦截器 request fulfilled入参
interface RequestReturnFulfilled {
  (fulfilled: AxiosRequestConfig<any>): any
}
// 拦截器 response fulfilled入参
interface ResponseReturnFulfilled {
  (response: AxiosResponse<any, any>): any
}
// 拦截器 Reject入参
interface ReturnReject {
  (error: any): Promise<any>
}

interface Interceptors<T> {
  (instance: AxiosInstance | undefined,
    fulfilled?: T | undefined,
    reject?: ReturnReject | undefined): void
}

// 包装请求的参数
interface requestBody {
  (url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<any, any>>
}

// 包装的请求
interface injectionRequestBody {
  /**
   * get请求
   * @param url string
   * @param data? any
   * @param config? AxiosRequestConfig
   */
  get: requestBody
  /**
   * post请求 默认json
   * @param url string
   * @param data? any
   * @param config? AxiosRequestConfig
   */
  post: requestBody
  /**
   * post请求 转成form
   * 请求头为headers: { 'content-type': 'application/x-www-form-urlencoded' } 使用post请求
   * @param url string
   * @param data? any
   * @param config? AxiosRequestConfig
   */
  formPost: requestBody
}


/**
 * 注入请求 生成包装过的请求
 * @param instance
 * @returns injectionRequest
 */
export const injectionRequestUse: (instance: AxiosInstance | undefined) => injectionRequestBody =
  (instance) => {
    if (!instance) throw new Error("实例不能为空");
    const injectionRequest = {
      get: get(instance),
      post: post(instance),
      formPost: formPost(instance),
    }
    return injectionRequest;
  }

/**
 * axios的request拦截
 * @param instance axios实例
 * @param fulfilled 成功方法
 * @param reject 失败方法
 * @returns util对象
 */
export const interceptorsRequestUse: Interceptors<RequestReturnFulfilled> =
  (instance, fulfilled, reject) => {
    if (!instance) throw new Error("实例不能为空");
    if (!fulfilled) {
      fulfilled = (config) => {
        return config;
      }
    }
    if (!reject) {
      reject = (error) => {
        return Promise.reject(error);
      }
    }
    instance.interceptors.request.use(fulfilled, reject);
  }

/**
 * axios的response拦截
 * @param instance axios实例
 * @param fulfilled 成功方法
 * @param reject 失败方法
 * @returns util对象
 */
export const interceptorsResponseUse: Interceptors<ResponseReturnFulfilled> =
  (instance, fulfilled, reject) => {
    if (!instance) throw new Error("实例不能为空");
    if (!fulfilled) {
      fulfilled = (response) => {
        return response.data;
      }
    }
    if (!reject) {
      reject = (error) => {
        return Promise.reject(error);
      }
    }
    instance.interceptors.response.use(fulfilled, reject);
  }

/**
 * 返回一个对象 可以链式调用 注册拦截方法 和生成请求
 * @returns {injectionRequestUse,interceptorsRequestUse,interceptorsResponseUse}
 */
const instanceUtil = (param: AxiosInstance | undefined) => {
  if (!param) throw new Error("实例不能为空");
  const instance: AxiosInstance = param;
  const temp = {
    injectionRequestUse: () => {
      return injectionRequestUse(instance);
    },
    interceptorsRequestUse: function (fulfilled?: RequestReturnFulfilled | undefined, reject?: ReturnReject | undefined) {
      interceptorsRequestUse(instance, fulfilled, reject)
      return temp;
    },
    interceptorsResponseUse: function (fulfilled?: RequestReturnFulfilled | undefined, reject?: ReturnReject | undefined) {
      interceptorsResponseUse(instance, fulfilled, reject)
      return temp;
    },
    setBaseURL(url:string){
      instance.defaults.baseURL = url;
      return temp
    },
    setRequestTimeout(time:number){
      instance.defaults.timeout = time;
      return temp
    }
  }
  return temp;
}

export default instanceUtil;

/**
 * get请求
 * @param url string
 * @param data? any
 * @param config? AxiosRequestConfig
 */
export const get = (instance: AxiosInstance) => {
  return (url: string, data?: any, config?: AxiosRequestConfig) => {
    config ? config.params = data : config = { params: data };
    return instance.get(url, config);
  }
};

/**
 * post请求 默认json
 * @param url string
 * @param data? any
 * @param config? AxiosRequestConfig
 */
export const post = (instance: AxiosInstance) => {
  return (url: string, data?: any, config?: AxiosRequestConfig) => {
    return instance.post(url, data, config);
  }

};

/**
 * post请求 转成form
 * 请求头为headers: { 'content-type': 'application/x-www-form-urlencoded' } 使用post请求
 * @param url string
 * @param data? any
 * @param config? AxiosRequestConfig
 */
export const formPost = (instance: AxiosInstance) => {
  return (url: string, data?: any, config?: AxiosRequestConfig) => {
    if (!config) {
      config = {
        headers: {
          "content-type": "application/x-www-form-urlencoded"
        }
      };
    } else {
      !config.headers ? config.headers = {
        "content-type": "application/x-www-form-urlencoded"
      } : config.headers["content-type"] = "application/x-www-form-urlencoded";
    }
    data = qs.stringify(data, { arrayFormat: "brackets" })
    return instance.post(url, data, config);
  }
};


